﻿using System;
using System.Collections.Generic;
using System.Configuration;
using System.Diagnostics;
using System.IO;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Text.RegularExpressions;
using System.Xml;
using NLog;
using Oracle.ManagedDataAccess.Client;

namespace Raise.Workbench.Tools {
    public static class Utils {
        private static readonly Logger Logger = LogManager.GetCurrentClassLogger(typeof(Utils));

        /// <summary>
        /// 获取数据库连接字符串
        /// </summary>
        /// <returns>队列名称</returns>
        public static string GetConnectString() {
            var reader = new AppSettingsReader();
            var queueName = reader.GetValue("ConnectionString", typeof(string));

            if(queueName == null)
                throw new KeyNotFoundException("配置文件中，ConnectionString配置节未找到，请重新配置");

            return queueName.ToString();
        }

        /// <summary>
        /// 测试数据库是否可以正常连接
        /// </summary>
        /// <param name="msg">返回连接的结果</param>
        /// <param name="connectionString">连接字符串</param>
        /// <returns>是否连接成功</returns>
        public static bool IsCanConnect(out string msg, string connectionString) {
            if(string.IsNullOrEmpty(connectionString))
                throw new Exception("IsCanConnect Parameter is not null");
            msg = string.Empty;
            try {
                using(var conn = new OracleConnection(GetConnectString())) {
                    conn.Open();
                }

                return true;
            } catch(Exception ex) {
                var stringBuilder = new StringBuilder();
                stringBuilder.AppendLine(connectionString);
                stringBuilder.AppendLine(ex.Message);
                msg = stringBuilder.ToString();
                return false;
            }
        }

        /// <summary>
        /// 格式化XML文件
        /// </summary>
        /// <param name="xml">XML报文</param>
        /// <returns>格式化的报文</returns>
        public static string FormatXml(object xml) {
            if(xml == null)
                return string.Empty;
            XmlDocument xd;
            var xmlDocument = xml as XmlDocument;
            if(xmlDocument != null) {
                xd = xmlDocument;
            } else {
                xd = new XmlDocument();
                xd.LoadXml(xml.ToString());
            }
            StringBuilder sb = new StringBuilder();
            StringWriter sw = new StringWriter(sb);
            XmlTextWriter xtw = null;
            try {
                xtw = new XmlTextWriter(sw);
                xtw.Formatting = Formatting.Indented;
                xtw.Indentation = 1;
                xtw.IndentChar = '\t';
                xd.WriteTo(xtw);
            } finally {
                xtw?.Close();
            }
            return sb.ToString();
        }

        /// <summary>
        /// 单实例程序控制，每次只能启动一个程序
        /// </summary>
        /// <returns>是否可以打开</returns>
        public static bool HasRunning() {
            Process currentProcess = Process.GetCurrentProcess();
            Process[] processCollection = Process.GetProcessesByName(currentProcess.ProcessName);
            foreach(Process p in processCollection) {
                if(p.Id == currentProcess.Id) {
                    return true;
                }
            }
            return false;
        }

        /// <summary>
        /// 获取本机的IP地址
        /// </summary>
        /// <returns>返回本机的IP 地址</returns>
        public static List<IPAddress> GetHostIpList() {
            string name = Dns.GetHostName();
            IPAddress[] ipadrlist = Dns.GetHostAddresses(name);

            var interNetwork = new List<IPAddress>();
            foreach(IPAddress ipa in ipadrlist) {
                if(ipa.AddressFamily == AddressFamily.InterNetwork)
                    interNetwork.Add(ipa);
            }

            return interNetwork;
        }

        /// <summary>
        /// 获取事务Id
        /// </summary>
        /// <param name="xml">报文</param>
        /// <returns>事务Id</returns>
        public static string GetBizTransactionId(string xml) {
            string bizTransactionIdElement = string.Empty;
            try {
                MatchCollection collection = Regex.Matches(xml, @"<BIZTRANSACTIONID.*>?.*<?\/BIZTRANSACTIONID>");
                if(collection.Count > 1)
                    throw new Exception("报文解析BIZTRANSACTIONID出错");

                bizTransactionIdElement = collection[0].Value;
                if(string.IsNullOrEmpty(bizTransactionIdElement))
                    throw new Exception("报文解析BIZTRANSACTIONID出错");
                var bizTransactionId = bizTransactionIdElement.Replace("<BIZTRANSACTIONID>", "").Replace("</BIZTRANSACTIONID>", "");
                bizTransactionId = bizTransactionId.Replace("<BIZTRANSACTIONID type=\"string\">", "");

                return bizTransactionId;
            } catch(Exception ex) {
                Logger.Error(ex.Message);
                //解析出错后，将整个BIZTRANSACTIONID标签进行存储
                return bizTransactionIdElement;
            }
        }

        /// <summary>
        /// 唯一标识
        /// </summary>
        public static string Guid => System.Guid.NewGuid().ToString().Replace("-", "").ToUpper();

        /// <summary>
        /// 获取当前源码的行号
        /// </summary>
        /// <returns>行号</returns>
        public static int GetLineNumber() {
            StackTrace st = new StackTrace(1, true);
            return st.GetFrame(0).GetFileLineNumber();
        }

        /// <summary>
        /// 取当前源码的源文件名
        /// </summary>
        /// <returns>文件名</returns>
        public static string GetCurSourceFileName() {
            StackTrace st = new StackTrace(1, true);
            return st.GetFrame(0).GetFileName();
        }
    }
}
